/*
 * Copyright (c) 2020 pig4cloud Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.love.cloud.admin.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.love.cloud.admin.api.entity.SysDept;
import com.love.cloud.admin.api.entity.SysUserDept;
import com.love.cloud.admin.mapper.SysDeptMapper;
import com.love.cloud.admin.mapper.SysUserDeptMapper;
import com.love.cloud.admin.service.SysDeptService;
import com.love.cloud.common.core.exception.BusinessException;
import com.love.cloud.common.mybatis.util.PageUtils;
import com.love.cloud.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门管理 服务实现类
 * </p>
 *
 * @author lengleng
 * @since 2019/2/1
 */
@Service
@RequiredArgsConstructor
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {
	@Resource
	private SysUserDeptMapper sysUserDeptMapper;

	@Resource
	private PageUtils pageUtils;

	/**
	 * 添加信息部门
	 * @param sysDept 部门
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveDept(SysDept sysDept) {
		//判断是否右重复名称的数据
		this.checkSaveOrUpdate(sysDept);
		//获取到父节点的信息
		SysDept parentSysDept = this.getById(sysDept.getParentId());
		//获取到最新的拼音信息
		sysDept.setFirstSpell(PinyinUtil.getFirstLetter(sysDept.getName(),""));
		sysDept.setSpell(PinyinUtil.getPinyin(sysDept.getName(),""));
		this.save(sysDept);
		//重新将部门路径设置进去
		sysDept.setPath(parentSysDept.getPath()+"/"+sysDept.getId());
		this.updateById(sysDept);
		return Boolean.TRUE;
	}

	/**
	 * 删除部门
	 * @param id 部门 ID
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeDeptById(Long id) {
		SysDept sysDept = this.getById(id);
		if(sysDept==null){
			throw new BusinessException("获取到部门信息为空,请传入正常部门信息");
		}
		//获取到下级部门
		QueryWrapper<SysDept> queryWrapper=new QueryWrapper<>();
		queryWrapper.lambda().likeRight(SysDept::getPath,sysDept.getPath());
		List<SysDept> list = this.list(queryWrapper);
		for (SysDept sysDeptItem :list) {
			this.removeById(sysDeptItem.getId());
			//删除掉对应用户部关系
			QueryWrapper<SysUserDept> sysUserDeptQueryWrapper=new QueryWrapper<>();
			sysUserDeptQueryWrapper.lambda().eq(SysUserDept::getDeptId,sysDeptItem.getId());
			sysUserDeptMapper.delete(sysUserDeptQueryWrapper);
		}
		return Boolean.TRUE;
	}

	/**
	 * 更新部门
	 * @param sysDept 部门信息
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateDeptById(SysDept sysDept) {
		this.checkSaveOrUpdate(sysDept);
		if(StringUtils.isNotEmpty(sysDept.getName())){
			//获取到最新的拼音信息
			sysDept.setFirstSpell(PinyinUtil.getFirstLetter(sysDept.getName(),""));
			sysDept.setSpell(PinyinUtil.getPinyin(sysDept.getName(),""));
		}
		//获取到父节点的信息
		SysDept parentSysDept = this.getById(sysDept.getParentId());
		//重新将部门路径设置进去
		sysDept.setPath(parentSysDept.getPath()+"/"+sysDept.getId());
		// 更新部门状态
		this.updateById(sysDept);
		return Boolean.TRUE;
	}

	@Override
	public List<TreeNode<Long>> listDeptLazyTrees(Long id) {
		if(id ==null){
			id = Long.valueOf(0);
		}
		QueryWrapper<SysDept> queryWrapper=new QueryWrapper<>();
		queryWrapper.lambda().eq(SysDept::getParentId,id);
		List<SysDept> depts=this.list(queryWrapper);
		List<TreeNode<Long>> collect = depts.stream()
				.filter(dept -> dept.getId().intValue() != dept.getParentId())
				.sorted(Comparator.comparingInt(SysDept::getSort)).map(dept -> {
					TreeNode<Long> treeNode = new TreeNode();
					treeNode.setId(dept.getId());
					treeNode.setParentId(dept.getParentId());
					treeNode.setName(dept.getName());
					Map<String,Object> extra=new HashMap<>();
					extra.put("path",dept.getPath());
					extra.put("spell",dept.getSpell());
					extra.put("firstSpell",dept.getFirstSpell());
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList());
		return collect;
	}

	@Override
	public IPage getDeptPage(Page page, SysDept sysDept) {
		if(sysDept.getId()==null){
			sysDept.setParentId(Long.valueOf(0));
		}
		QueryWrapper<SysDept> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda()
				.eq(SysDept::getParentId,sysDept.getParentId())
				.like(StringUtils.isNotEmpty(sysDept.getName()),SysDept::getName,sysDept.getName());
		return page(pageUtils.page(), queryWrapper);
	}


	/**
	 * 查询全部部门树
	 * @return 树
	 */
	@Override
	public List<Tree<Long>> listDeptTrees() {
		return getDeptTree(this.list(Wrappers.emptyWrapper()));
	}

	/**
	 * 查询用户部门树
	 * @return
	 */
	@Override
	public List<Tree<Long>> listCurrentUserDeptTrees() {
		List<SysDept> deptList = SecurityUtils.getUser().getDeptList();
		return getDeptTree(deptList);
	}



	/**
	 * 构建部门树
	 * @param depts 部门
	 * @return
	 */
	private List<Tree<Long>> getDeptTree(List<SysDept> depts) {
		List<TreeNode<Long>> collect = depts.stream()
				.filter(dept -> dept.getId().intValue() != dept.getParentId())
				.sorted(Comparator.comparingInt(SysDept::getSort)).map(dept -> {
					TreeNode<Long> treeNode = new TreeNode();
					treeNode.setId(dept.getId());
					treeNode.setParentId(dept.getParentId());
					treeNode.setName(dept.getName());
					Map<String,Object> extra=new HashMap<>();
					extra.put("path",dept.getPath());
					extra.put("spell",dept.getSpell());
					extra.put("firstSpell",dept.getFirstSpell());
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList());

		return TreeUtil.build(collect, 0L);
	}
	/**
	 * 校验是否可以保存或者更新
	 */
	private void checkSaveOrUpdate(SysDept sysDept){
		if(sysDept==null){
			throw new BusinessException("部门数据为空");
		}
		QueryWrapper<SysDept> queryWrapper=new QueryWrapper<>();
		queryWrapper.lambda().ne(sysDept.getId()!=null,SysDept::getId,sysDept.getId())
				.eq(SysDept::getName,sysDept.getName());
		List<SysDept> list = this.list(queryWrapper);
		if(list!=null&&list.size()>0){
			throw new BusinessException("已经有部门名为"+sysDept.getName());
		}
	}


}
